﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace System.ComponentModel
{
    /// <summary>
    /// Represents a factory method that can create object instances as needed.
    /// </summary>
    /// <param name="objectType">The type of object to create.</param>
    /// <param name="container">The container that is requesting the creation of the object.</param>
    /// <param name="isSingleInstance">Whether the returned object is to be treated as a singleton.</param>
    /// <returns></returns>
    public delegate object ComponentCreator(Type objectType, IComponentContainer container, out bool isSingleInstance);

    /// <summary>
    /// Encapsulates the functionality of a container that defines a scope of
    /// composition where objects can be registered and dependencies can be resolved.
    /// </summary>
    public interface IComponentContainer
    {

        /// <summary>
        /// Gets an instance of an object for the specified object type.
        /// </summary>
        /// <param name="objectType">The type of object to retrieve.</param>
        /// <returns>The resulting object; null if the object could not be retrieved.</returns>
        object GetObject(Type objectType);

        /// <summary>
        /// Gets an instance of an object for the specified object type.
        /// </summary>
        /// <typeparam name="TObject">The type of object to retrieve.</typeparam>
        /// <returns>The resulting object; null if the object could not be retrieved.</returns>
        TObject GetObject<TObject>();

        /// <summary>
        /// Initializes an object instance by resolving its dependencies against
        /// objects registered in the container.
        /// </summary>
        /// <param name="objectInstance">The object to initialize.</param>
        /// <returns>true if the object could be initialized; false if it couldn't.</returns>
        bool InitializeObject(object objectInstance);

        /// <summary>
        /// Registers an object instance with the container. If the object is marked
        /// with ServiceAttribute metadata, then the object is registered for those
        /// service types; otherwise it is registered as the implementation of its own
        /// type.
        /// </summary>
        /// <param name="objectInstance">The object to register.</param>
        void RegisterObject(object objectInstance);

        /// <summary>
        /// Registers an object instance for the specified type with the container.
        /// </summary>
        /// <param name="objectType">The type of object this instance corresponds to.</param>
        /// <param name="objectInstance">The object to register.</param>
        void RegisterObject(Type objectType, object objectInstance);

        /// <summary>
        /// Registers an object creator or factory for the specified type with the container.
        /// </summary>
        /// <param name="objectType">The type of object this factory corresponds to.</param>
        /// <param name="objectCreator">The factory to register.</param>
        void RegisterObject(Type objectType, ComponentCreator objectCreator);
    }
}
